<?php
// 应用公共文件

use app\libraries\exception\ApiException;
use app\libraries\utils\Trace;
use app\libraries\utils\Util;
use think\facade\Event;
use think\facade\Log;

if (!function_exists('get_property')) {
    /**
     * 获取指定类中的指定数据
     *
     * @Author YangHB
     * @DateTime 2022-07-12 09:55:56
     *
     * @param object|array|string $obj
     * @param string $property
     * @param object $default
     * @return object|string|array|mixed
     */
    function get_property($obj, $property, $default = null)
    {
        if (!$obj) {
            return $default;
        }
        if (is_string($obj)) {
            $obj = json_decode($obj, true);
        }
        if (is_object($obj)) {
            if (property_exists($obj, $property)) {
                return $obj->$property;
            }
            return isset($obj->$property) ? $obj->$property : $default;
        }

        return isset($obj[$property]) ? $obj[$property] : $default;
    }
}
if (!function_exists('get_value')) {
    /**
     * 获取指定类中的属性
     *
     * @Author YangHB
     * @DateTime 2022-07-13 09:55:34
     *
     * @return object|string|array|mixed
     */
    function get_value()
    {
        $args = func_get_args();
        $value = null;
        switch (count($args)) {
            case 2:
                //单一变量
                [$_data, $_default_value] = $args;
                $value = $_default_value;
                if (!is_null($_data)) {
                    $value = $_data;
                }
                break;
            case 3:
                //数组或对象
                [$_data, $_key, $_default_value] = $args;
                $value = get_property($_data, $_key, $_default_value);
                break;
            case 4:
                //数组或对象+回调函数
                [$_data, $_key, $_default_value, $_closure] = $args;
                $value = get_property($_data, $_key, $_default_value);
                if ('Closure' == get_class($_closure)) {
                    $value = $_closure($value);
                }
                break;
            default:
                break;
        }

        return $value;
    }
}
if (!function_exists('is_true')) {
    /**
     * 返回判断是否为 bool 型
     *
     * @Author YangHB
     * @DateTime 2022-07-12 13:32:56
     *
     * @param mixed $val
     * @param boolean $returnNull
     * @return boolean
     */
    function is_true($val, $returnNull = false): bool
    {
        $boolval = (is_string($val) ? filter_var($val, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) : (bool)$val);
        return ($boolval === null && !$returnNull ? false : $boolval);
    }
}
if (!function_exists('blank')) {
    /**
     * Determine if the given value is "blank".
     *
     * @param mixed $value
     * @return bool
     */
    function blank($value)
    {
        if (is_null($value)) {
            return true;
        }

        if (is_string($value)) {
            return trim($value) === '';
        }

        if (is_numeric($value) || is_bool($value)) {
            return false;
        }

        if ($value instanceof Countable) {
            return count($value) === 0;
        }

        return empty($value);
    }
}
if (!function_exists('get_sequuid')) {
    /**
     * 返回 有序 uuid
     */
    function get_sequuid(bool $noLine = false, int $exType = 11): string
    {
        if (function_exists('uuid_create')) {
            $uuid = uuid_create($exType);
            if ($noLine) {
                return str_replace('-', '', $uuid);
            }
            return $uuid;
        }
        return "";
    }
}
if (!function_exists('get_guid')) {
    /**
     * 返回 有序 guid
     */
    function get_guid(): string
    {
        return str_replace("-", "", get_sequuid());
    }
}
if (!function_exists('getmicrotime')) {
    function getmicrotime(): string
    {
        [$t1, $t2] = explode(' ', microtime());
        return bcadd($t1, $t2, 8);
    }
}
if (!function_exists('throwException')) {
    /**
     * 异常统一抛出方式
     *
     * @param  array  $error
     * @param  array|string  $argv
     * @param  array  $logData
     * @param  string  $level
     * @throws ApiException
     */
    function throwException(array $error, $argv = [], array $logData = [], string $level = 'LogInfo')
    {
        Util::throwException($error, $argv, $logData, $level);
    }
}
if (!function_exists('un_camelize')) {
    /**
     * 驼峰转下划线
     * @param $camelCaps
     * @param string $separator
     * @return string
     */
    function un_camelize($camelCaps, $separator = '_'): string
    {
        return strtolower(preg_replace('/([a-z])([A-Z])/', "$1" . $separator . "$2", $camelCaps));
    }
}
if (!function_exists('camelize')) {
    /**
     * 下划线转驼峰
     * @param $unCamelizeWords
     * @param string $separator
     * @return string
     */
    function camelize($unCamelizeWords, $separator = '_'): string
    {
        $unCamelizeWords = $separator . str_replace($separator, " ", strtolower($unCamelizeWords));

        return ltrim(str_replace(" ", "", ucwords($unCamelizeWords)), $separator);
    }
}
if (!function_exists('fen_to_yuan')) {
    /**
     * 分转元
     * @param $price
     * @return string|null
     */
    function fen_to_yuan($price): ?string
    {
        $price = bcdiv($price, 100, 2);
        return rtrim(rtrim($price, '0'), '.');
    }
}
if (!function_exists('yuan_to_fen')) {
    /**
     * 元转分
     * @param $price
     * @return int
     */
    function yuan_to_fen($price): int
    {
        return (int)bcmul($price, 100);
    }
}

if (!function_exists('ratio_to_number')) {
    /**
     * 百分比转数字，所得结果单位 1/10000。可直接用于金额比列计算
     * @param $ratio
     * @return int
     */
    function ratio_to_number($ratio): int
    {
        return (int)bcmul($ratio, 100);
    }
}

if (!function_exists('number_to_ratio')) {
    /**
     * 数字转百分比，所得结果单位 1/100
     *
     * @param $number
     * @return string
     */
    function number_to_ratio($number): string
    {
        $price = bcdiv($number, 100, 2);
        return rtrim(rtrim($price, '0'), '.');
    }
}

if (!function_exists('fen_ratio_to_milli')) {
    /**
     * 用于金额比列计算后转换成正常金额值，金额计算单位（分）、比列计算单位 1/10000
     * 转换后，金额单位（元）、比列单位 1
     *
     * @param $number
     * @return string
     */
    function number_to_milli($number): string
    {
        $price = bcdiv($number, 10000 * 100, 2);
        return rtrim(rtrim($price, '0'), '.');
    }
}

//记录日志函数
if (!function_exists('LogWrite')) {
    /**
     * 底层输出日志
     *
     * @Author YangHB
     * @DateTime 2022-07-13 13:34:24
     *
     * @param string $level
     * @param string $chan
     * @param string $title
     * @param string $msg
     * @param array $content
     * @param array $param
     * @return void
     */
    function LogWrite(string $level, string $chan, string $title, string $msg, array $content = [], array $param = [])
    {
        Log::$level([
            'chan' => $chan,
            'title' => $title,
            'msg' => $msg,
            'content' => $content,
            'file_line' => Trace::getInstance()->getFileLine(),
        ], $param);
    }
}
if (!function_exists('LogInfo')) {
    /**
     * 记录 Info 组别日志
     *
     * @Author YangHB
     * @DateTime 2022-07-13 11:28:59
     *
     * @param string $chan
     * @param string $title
     * @param string $msg
     * @param array $content
     * @param array $param
     * @return void
     */
    function LogInfo(string $chan, string $title, string $msg, array $content = [], array $param = [])
    {
        LogWrite('info', $chan, $title, $msg, $content, $param);
    }
}
if (!function_exists('LogWarning')) {
    /**
     * 记录警告组别日志
     *
     * @Author YangHB
     * @DateTime 2022-07-13 11:30:12
     *
     * @param string $chan
     * @param string $title
     * @param string $msg
     * @param array $content
     * @param array $param
     * @return void
     */
    function LogWarning(string $chan, string $title, string $msg, array $content = [], array $param = [])
    {
        LogWrite('warning', $chan, $title, $msg, $content, $param);
    }
}
if (!function_exists('LogError')) {
    /**
     * 记录错误级别日志信息
     *
     * @Author YangHB
     * @DateTime 2022-07-13 11:30:56
     *
     * @param string $chan
     * @param string $title
     * @param string $msg
     * @param array $content
     * @param array $param
     * @return void
     */
    function LogError(string $chan, string $title, string $msg, array $content = [], array $param = [])
    {
        LogWrite('error', $chan, $title, $msg, $content, $param);
    }
}
if (!function_exists('LogAlert')) {
    /**
     * 记录警醒级别日志信息
     *
     * @Author YangHB
     * @DateTime 2022-07-13 11:31:30
     *
     * @param string $chan
     * @param string $title
     * @param string $msg
     * @param array $content
     * @param array $param
     * @return void
     */
    function LogAlert(string $chan, string $title, string $msg, array $content = [], array $param = [])
    {
        LogWrite('alert', $chan, $title, $msg, $content, $param);
    }
}
if (!function_exists('LogCritical')) {
    /**
     * 记录紧急型错误信息
     *
     * @Author YangHB
     * @DateTime 2022-07-13 11:33:13
     *
     * @param string $chan
     * @param string $title
     * @param string $msg
     * @param array $content
     * @param array $param
     * @return void
     */
    function LogCritical(string $chan, string $title, string $msg, array $content = [], array $param = [])
    {
        LogWrite('critical', $chan, $title, $msg, $content, $param);
    }
}
if (!function_exists('LogDebug')) {
    /**
     * 记录调整日志错误信息
     *
     * @Author YangHB
     * @DateTime 2022-07-13 11:33:48
     *
     * @param string $chan
     * @param string $title
     * @param string $msg
     * @param array $content
     * @param array $param
     * @return void
     */
    function LogDebug(string $chan, string $title, string $msg, array $content = [], array $param = [])
    {
        LogWrite('debug', $chan, $title, $msg, $content, $param);
    }
}
//36进制
if (!function_exists('get_base_carry_char')) {
    /**
     * @desc im:十进制数转换成三十六机制数
     * @param (int)$num 十进制数
     * @param (int)$len 前面补齐的长度
     * return string 三十六进制数
     */
    function get_base_carry_char(int $num, int $len = 5, $carry = 0): string
    {
        if ($len < 1) {
            $len = 1;
        }
        $num = intval($num);
        if ($num < 0) {
            return false;
        }
        $charArr = array(
            "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", 'A', 'B', 'C', 'D', 'E',
            'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
            'U', 'V', 'W', 'X', 'Y', 'Z'
        );
        $dNum = ($carry > 0 && $carry <= count($charArr)) ? $carry : (int)count($charArr);
        $char = '';
        do {
            $key = bcmod($num, $dNum);
            $char = $charArr[$key] . $char;
            $num = bcdiv($num, $dNum, 0);
        } while ($num > 0);
        return sprintf('%0' . $len . 's', $char);
    }
}
if (!function_exists('get_base_carry_char_num')) {
    /**
     * @desc im:三十六进制数转换成十机制数
     * @param (string)$char 三十六进制数
     * return int 十进制数
     */
    function get_base_carry_char_num(string $char, $carry = 0): int
    {
        $charArr = array(
            "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E",
            "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
            "U", "V", "W", "X", "Y", "Z"
        );
        $sum = 0;
        $dNum = ($carry > 0 && $carry <= count($charArr)) ? $carry : (int)count($charArr);
        $len = strlen($char);
        for ($i = 0; $i < $len; $i++) {
            $index = array_search($char[$i], $charArr);
            $sum = bcadd(bcmul($index, bcpow($dNum, $len - $i - 1, 0), 0), $sum, 0);
        }
        return $sum;
    }
}
if (!function_exists('encMe')) {
    function DE_RM($a, $bit)
    {
        $b = unpack('I', pack('I', $a))[1];
        if ($bit > 0) {
            return unpack('i', pack('i', $b >> $bit))[1];
        } else {
            $bit = $bit * -1;

            return unpack('i', pack('i', $b << $bit))[1];
        }
    }

    function DE_stringToHex($s)
    {
        return bin2hex($s);
    }

    function DE_HexTostring($s)
    {
        return hex2bin($s);
    }

    function DE_des_createKeys($beinetkey)
    {
        $pc2bytes0 = array(0, 0x4, 0x20000000, 0x20000004, 0x10000, 0x10004, 0x20010000, 0x20010004,
            0x200, 0x204, 0x20000200, 0x20000204, 0x10200, 0x10204, 0x20010200, 0x20010204);
        $pc2bytes1 = array(0, 0x1, 0x100000, 0x100001, 0x4000000, 0x4000001, 0x4100000, 0x4100001,
            0x100, 0x101, 0x100100, 0x100101, 0x4000100, 0x4000101, 0x4100100, 0x4100101);
        $pc2bytes2 = array(0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808, 0, 0x8,
            0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808);
        $pc2bytes3 = array(0, 0x200000, 0x8000000, 0x8200000, 0x2000, 0x202000, 0x8002000, 0x8202000,
            0x20000, 0x220000, 0x8020000, 0x8220000, 0x22000, 0x222000, 0x8022000, 0x8222000);
        $pc2bytes4 = array(0, 0x40000, 0x10, 0x40010, 0, 0x40000, 0x10, 0x40010, 0x1000, 0x41000, 0x1010,
            0x41010, 0x1000, 0x41000, 0x1010, 0x41010);
        $pc2bytes5 = array(0, 0x400, 0x20, 0x420, 0, 0x400, 0x20, 0x420, 0x2000000, 0x2000400, 0x2000020,
            0x2000420, 0x2000000, 0x2000400, 0x2000020, 0x2000420);
        $pc2bytes6 = array(0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002, 0,
            0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002);
        $pc2bytes7 = array(0, 0x10000, 0x800, 0x10800, 0x20000000, 0x20010000, 0x20000800, 0x20010800, 0x20000,
            0x30000, 0x20800, 0x30800, 0x20020000, 0x20030000, 0x20020800, 0x20030800);
        $pc2bytes8 = array(0, 0x40000, 0, 0x40000, 0x2, 0x40002, 0x2, 0x40002, 0x2000000, 0x2040000, 0x2000000,
            0x2040000, 0x2000002, 0x2040002, 0x2000002, 0x2040002);
        $pc2bytes9 = array(0, 0x10000000, 0x8, 0x10000008, 0, 0x10000000, 0x8, 0x10000008, 0x400, 0x10000400, 0x408,
            0x10000408, 0x400, 0x10000400, 0x408, 0x10000408);
        $pc2bytes10 = array(0, 0x20, 0, 0x20, 0x100000, 0x100020, 0x100000, 0x100020, 0x2000, 0x2020, 0x2000, 0x2020,
            0x102000, 0x102020, 0x102000, 0x102020);
        $pc2bytes11 = array(0, 0x1000000, 0x200, 0x1000200, 0x200000, 0x1200000, 0x200200, 0x1200200, 0x4000000,
            0x5000000, 0x4000200, 0x5000200, 0x4200000, 0x5200000, 0x4200200, 0x5200200);
        $pc2bytes12 = array(0, 0x1000, 0x8000000, 0x8001000, 0x80000, 0x81000, 0x8080000, 0x8081000, 0x10, 0x1010,
            0x8000010, 0x8001010, 0x80010, 0x81010, 0x8080010, 0x8081010);
        $pc2bytes13 = array(0, 0x4, 0x100, 0x104, 0, 0x4, 0x100, 0x104, 0x1, 0x5, 0x101, 0x105, 0x1, 0x5, 0x101, 0x105);

        $iterations = strlen($beinetkey) >= 24 ? 3 : 1;
        $keys = array();
        $shifts = array(0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0);
        $left = 0;
        $right = 0;
        $lefttemp = 0;
        $righttemp = 0;
        $m = 0;
        $n = 0;
        $temp = 0;

        for ($j = 0; $j < $iterations; ++$j) { //either 1 or 3 iterations
            $tmp = array(0, 0, 0, 0, 0, 0, 0, 0);
            $pos = 24;
            $iTmp = 0;
            while ($m < strlen($beinetkey) && $iTmp < count($tmp)) {
                if ($pos < 0) {
                    $pos = 24;
                }
                $tmp[$iTmp++] = ord($beinetkey[$m++]) << $pos;
                $pos -= 8;
            }
            $left = $tmp[0] | $tmp[1] | $tmp[2] | $tmp[3];
            $right = $tmp[4] | $tmp[5] | $tmp[6] | $tmp[7];
            $temp = (DE_RM($left, 4) ^ $right) & 0x0f0f0f0f;
            $right ^= $temp;
            $left ^= DE_RM($temp, -4);
            $temp = (DE_RM($right, 16) ^ $left) & 0x0000ffff;
            $left ^= $temp;
            $right ^= DE_RM($temp, -16);
            $temp = (DE_RM($left, 2) ^ $right) & 0x33333333;
            $right ^= $temp;
            $left ^= DE_RM($temp, -2);
            $temp = (DE_RM($right, 16) ^ $left) & 0x0000ffff;
            $left ^= $temp;
            $right ^= DE_RM($temp, -16);
            $temp = (DE_RM($left, 1) ^ $right) & 0x55555555;
            $right ^= $temp;
            $left ^= DE_RM($temp, -1);
            $temp = (DE_RM($right, 8) ^ $left) & 0x00ff00ff;
            $left ^= $temp;
            $right ^= DE_RM($temp, -8);
            $temp = (DE_RM($left, 1) ^ $right) & 0x55555555;
            $right ^= $temp;
            $left ^= DE_RM($temp, -1);
            $temp = DE_RM($left, -8) | (DE_RM($right, 20) & 0x000000f0);
            $left = DE_RM($right, -24) | (DE_RM($right, -8) & 0xff0000) | (DE_RM($right, 8) & 0xff00) | (DE_RM($right, 24) & 0xf0);
            $right = $temp;

            for ($i = 0; $i < count($shifts); ++$i) {
                if (1 == $shifts[$i]) {
                    $left = ($left << 2) | DE_RM($left, 26);
                    $right = ($right << 2) | DE_RM($right, 26);
                } else {
                    $left = ($left << 1) | DE_RM($left, 27);
                    $right = ($right << 1) | DE_RM($right, 27);
                }
                $left &= -0xf;
                $right &= -0xf;

                $lefttemp = $pc2bytes0[DE_RM($left, 28)] | $pc2bytes1[DE_RM($left, 24) & 0xf]
                    | $pc2bytes2[DE_RM($left, 20) & 0xf] | $pc2bytes3[DE_RM($left, 16) & 0xf]
                    | $pc2bytes4[DE_RM($left, 12) & 0xf] | $pc2bytes5[DE_RM($left, 8) & 0xf]
                    | $pc2bytes6[DE_RM($left, 4) & 0xf];
                $righttemp = $pc2bytes7[DE_RM($right, 28)] | $pc2bytes8[DE_RM($right, 24) & 0xf]
                    | $pc2bytes9[DE_RM($right, 20) & 0xf] | $pc2bytes10[DE_RM($right, 16) & 0xf]
                    | $pc2bytes11[DE_RM($right, 12) & 0xf] | $pc2bytes12[DE_RM($right, 8) & 0xf]
                    | $pc2bytes13[DE_RM($right, 4) & 0xf];
                $temp = (DE_RM($righttemp, 16) ^ $lefttemp) & 0x0000ffff;
                $keys[] = $lefttemp ^ $temp;
                ++$n;
                $keys[] = $righttemp ^ ($temp << 16);
                ++$n;
            }
        }

        return $keys;
    }

    function DE_des($beinetkey, $message, $encrypt, $mode, $iv)
    {
        //declaring this locally speeds things up a bit
        $spfunction1 = array(0x1010400, 0, 0x10000, 0x1010404, 0x1010004, 0x10404, 0x4, 0x10000,
            0x400, 0x1010400, 0x1010404, 0x400, 0x1000404, 0x1010004, 0x1000000, 0x4, 0x404, 0x1000400,
            0x1000400, 0x10400, 0x10400, 0x1010000, 0x1010000, 0x1000404, 0x10004, 0x1000004, 0x1000004,
            0x10004, 0, 0x404, 0x10404, 0x1000000, 0x10000, 0x1010404, 0x4, 0x1010000, 0x1010400, 0x1000000,
            0x1000000, 0x400, 0x1010004, 0x10000, 0x10400, 0x1000004, 0x400, 0x4, 0x1000404, 0x10404,
            0x1010404, 0x10004, 0x1010000, 0x1000404, 0x1000004, 0x404, 0x10404, 0x1010400, 0x404,
            0x1000400, 0x1000400, 0, 0x10004, 0x10400, 0, 0x1010004);
        $spfunction2 = array(-0x7fef7fe0, -0x7fff8000, 0x8000, 0x108020, 0x100000, 0x20, -0x7fefffe0,
            -0x7fff7fe0, -0x7fffffe0, -0x7fef7fe0, -0x7fef8000, -0x80000000, -0x7fff8000, 0x100000, 0x20,
            -0x7fefffe0, 0x108000, 0x100020, -0x7fff7fe0, 0, -0x80000000, 0x8000, 0x108020, -0x7ff00000,
            0x100020, -0x7fffffe0, 0, 0x108000, 0x8020, -0x7fef8000, -0x7ff00000, 0x8020, 0, 0x108020,
            -0x7fefffe0, 0x100000, -0x7fff7fe0, -0x7ff00000, -0x7fef8000, 0x8000, -0x7ff00000, -0x7fff8000,
            0x20, -0x7fef7fe0, 0x108020, 0x20, 0x8000, -0x80000000, 0x8020, -0x7fef8000, 0x100000, -0x7fffffe0,
            0x100020, -0x7fff7fe0, -0x7fffffe0, 0x100020, 0x108000, 0, -0x7fff8000, 0x8020, -0x80000000,
            -0x7fefffe0, -0x7fef7fe0, 0x108000);
        $spfunction3 = array(0x208, 0x8020200, 0, 0x8020008, 0x8000200, 0, 0x20208, 0x8000200, 0x20008,
            0x8000008, 0x8000008, 0x20000, 0x8020208, 0x20008, 0x8020000, 0x208, 0x8000000, 0x8, 0x8020200,
            0x200, 0x20200, 0x8020000, 0x8020008, 0x20208, 0x8000208, 0x20200, 0x20000, 0x8000208, 0x8,
            0x8020208, 0x200, 0x8000000, 0x8020200, 0x8000000, 0x20008, 0x208, 0x20000, 0x8020200, 0x8000200,
            0, 0x200, 0x20008, 0x8020208, 0x8000200, 0x8000008, 0x200, 0, 0x8020008, 0x8000208, 0x20000,
            0x8000000, 0x8020208, 0x8, 0x20208, 0x20200, 0x8000008, 0x8020000, 0x8000208, 0x208, 0x8020000,
            0x20208, 0x8, 0x8020008, 0x20200);
        $spfunction4 = array(0x802001, 0x2081, 0x2081, 0x80, 0x802080, 0x800081, 0x800001, 0x2001,
            0, 0x802000, 0x802000, 0x802081, 0x81, 0, 0x800080, 0x800001, 0x1, 0x2000, 0x800000, 0x802001,
            0x80, 0x800000, 0x2001, 0x2080, 0x800081, 0x1, 0x2080, 0x800080, 0x2000, 0x802080, 0x802081,
            0x81, 0x800080, 0x800001, 0x802000, 0x802081, 0x81, 0, 0, 0x802000, 0x2080, 0x800080, 0x800081,
            0x1, 0x802001, 0x2081, 0x2081, 0x80, 0x802081, 0x81, 0x1, 0x2000, 0x800001, 0x2001, 0x802080,
            0x800081, 0x2001, 0x2080, 0x800000, 0x802001, 0x80, 0x800000, 0x2000, 0x802080);
        $spfunction5 = array(0x100, 0x2080100, 0x2080000, 0x42000100, 0x80000, 0x100, 0x40000000, 0x2080000,
            0x40080100, 0x80000, 0x2000100, 0x40080100, 0x42000100, 0x42080000, 0x80100, 0x40000000, 0x2000000,
            0x40080000, 0x40080000, 0, 0x40000100, 0x42080100, 0x42080100, 0x2000100, 0x42080000, 0x40000100, 0,
            0x42000000, 0x2080100, 0x2000000, 0x42000000, 0x80100, 0x80000, 0x42000100, 0x100, 0x2000000,
            0x40000000, 0x2080000, 0x42000100, 0x40080100, 0x2000100, 0x40000000, 0x42080000, 0x2080100,
            0x40080100, 0x100, 0x2000000, 0x42080000, 0x42080100, 0x80100, 0x42000000, 0x42080100, 0x2080000,
            0, 0x40080000, 0x42000000, 0x80100, 0x2000100, 0x40000100, 0x80000, 0, 0x40080000, 0x2080100, 0x40000100);
        $spfunction6 = array(0x20000010, 0x20400000, 0x4000, 0x20404010, 0x20400000, 0x10, 0x20404010, 0x400000,
            0x20004000, 0x404010, 0x400000, 0x20000010, 0x400010, 0x20004000, 0x20000000, 0x4010, 0, 0x400010,
            0x20004010, 0x4000, 0x404000, 0x20004010, 0x10, 0x20400010, 0x20400010, 0, 0x404010, 0x20404000, 0x4010,
            0x404000, 0x20404000, 0x20000000, 0x20004000, 0x10, 0x20400010, 0x404000, 0x20404010, 0x400000, 0x4010,
            0x20000010, 0x400000, 0x20004000, 0x20000000, 0x4010, 0x20000010, 0x20404010, 0x404000, 0x20400000, 0x404010,
            0x20404000, 0, 0x20400010, 0x10, 0x4000, 0x20400000, 0x404010, 0x4000, 0x400010, 0x20004010, 0, 0x20404000,
            0x20000000, 0x400010, 0x20004010);
        $spfunction7 = array(0x200000, 0x4200002, 0x4000802, 0, 0x800, 0x4000802, 0x200802, 0x4200800, 0x4200802,
            0x200000, 0, 0x4000002, 0x2, 0x4000000, 0x4200002, 0x802, 0x4000800, 0x200802, 0x200002, 0x4000800, 0x4000002,
            0x4200000, 0x4200800, 0x200002, 0x4200000, 0x800, 0x802, 0x4200802, 0x200800, 0x2, 0x4000000, 0x200800,
            0x4000000, 0x200800, 0x200000, 0x4000802, 0x4000802, 0x4200002, 0x4200002, 0x2, 0x200002, 0x4000000, 0x4000800,
            0x200000, 0x4200800, 0x802, 0x200802, 0x4200800, 0x802, 0x4000002, 0x4200802, 0x4200000, 0x200800, 0, 0x2,
            0x4200802, 0, 0x200802, 0x4200000, 0x800, 0x4000002, 0x4000800, 0x800, 0x200002);
        $spfunction8 = array(0x10001040, 0x1000, 0x40000, 0x10041040, 0x10000000, 0x10001040, 0x40, 0x10000000,
            0x40040, 0x10040000, 0x10041040, 0x41000, 0x10041000, 0x41040, 0x1000, 0x40, 0x10040000, 0x10000040,
            0x10001000, 0x1040, 0x41000, 0x40040, 0x10040040, 0x10041000, 0x1040, 0, 0, 0x10040040, 0x10000040,
            0x10001000, 0x41040, 0x40000, 0x41040, 0x40000, 0x10041000, 0x1000, 0x40, 0x10040040, 0x1000, 0x41040,
            0x10001000, 0x40, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x40000, 0x10001040, 0, 0x10041040,
            0x40040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0, 0x10041040, 0x41000, 0x41000, 0x1040, 0x1040,
            0x40040, 0x10000000, 0x10041000);

        $keys = DE_des_createKeys($beinetkey);
        $m = 0;
        $i = 0;
        $j = 0;
        $temp = 0;
        $right1 = 0;
        $right2 = 0;
        $left = 0;
        $right = 0;
        $looping = array();
        $cbcleft = 0;
        $cbcleft2 = 0;
        $cbcright = 0;
        $cbcright2 = 0;
        $endloop = 0;
        $loopinc = 0;
        $len = strlen($message);
        $chunk = 0;
        //set up the loops for single and triple des
        $iterations = 32 == count($keys) ? 3 : 9; //single or triple des
        if (3 == $iterations) {
            $looping = $encrypt ? array(0, 32, 2) : array(30, -2, -2);
        } else {
            $looping = $encrypt ? array(0, 32, 2, 62, 30, -2, 64, 96, 2) : array(94, 62, -2, 32, 64, 2, 30, -2, -2);
        }

        if ($encrypt) {
            $message .= "\0\0\0\0\0\0\0\0"; //pad the message out with null bytes
        }
        $result = '';
        $tempresult = '';

        if ($mode) { //CBC mode
            $tmp = array(0, 0, 0, 0, 0, 0, 0, 0);
            $pos = 24;
            $iTmp = 0;
            while ($m < strlen($iv) && $iTmp < count($tmp)) {
                if ($pos < 0) {
                    $pos = 24;
                }
                $tmp[$iTmp++] = ord($iv[$m++]) << $pos;
                $pos -= 8;
            }
            $cbcleft = $tmp[0] | $tmp[1] | $tmp[2] | $tmp[3];
            $cbcright = $tmp[4] | $tmp[5] | $tmp[6] | $tmp[7];
            $m = 0;
        }

        while ($m < $len) {
            if ($encrypt) {/*加密时按双字节操作*/
                $left = (ord($message[$m++]) << 16) | ord($message[$m++]);
                $right = (ord($message[$m++]) << 16) | ord($message[$m++]);
            } else {
                $left = (ord($message[$m++]) << 24) | (ord($message[$m++]) << 16) | (ord($message[$m++]) << 8) | ord($message[$m++]);
                $right = (ord($message[$m++]) << 24) | (ord($message[$m++]) << 16) | (ord($message[$m++]) << 8) | ord($message[$m++]);
            }
            //for Cipher Block Chaining mode,xor the message with the previous result
            if ($mode) {
                if ($encrypt) {
                    $left ^= $cbcleft;
                    $right ^= $cbcright;
                } else {
                    $cbcleft2 = $cbcleft;
                    $cbcright2 = $cbcright;
                    $cbcleft = $left;
                    $cbcright = $right;
                }
            }

            $temp = (DE_RM($left, 4) ^ $right) & 0x0f0f0f0f;
            $right ^= $temp;
            $left ^= ($temp << 4);
            $temp = (DE_RM($left, 16) ^ $right) & 0x0000ffff;
            $right ^= $temp;
            $left ^= ($temp << 16);
            $temp = (DE_RM($right, 2) ^ $left) & 0x33333333;
            $left ^= $temp;
            $right ^= ($temp << 2);
            $temp = (DE_RM($right, 8) ^ $left) & 0x00ff00ff;
            $left ^= $temp;
            $right ^= ($temp << 8);
            $temp = (DE_RM($left, 1) ^ $right) & 0x55555555;
            $right ^= $temp;
            $left ^= ($temp << 1);

            $left = (($left << 1) | DE_RM($left, 31));
            $right = (($right << 1) | DE_RM($right, 31));

            for ($j = 0; $j < $iterations; $j += 3) {
                $endloop = $looping[$j + 1];
                $loopinc = $looping[$j + 2];
                //now go through and perform the encryption or decryption
                for ($i = $looping[$j]; $i != $endloop; $i += $loopinc) { //for efficiency
                    $right1 = $right ^ $keys[$i];
                    $right2 = (DE_RM($right, 4) | ($right << 28)) ^ $keys[$i + 1];
                    //the result is attained by passing these bytes through the S selection functions
                    $temp = $left;
                    $left = $right;
                    $right = intval($temp ^ ($spfunction2[DE_RM($right1, 24) & 0x3f] |
                            $spfunction4[DE_RM($right1, 16) & 0x3f] | $spfunction6[DE_RM($right1, 8) & 0x3f] |
                            $spfunction8[$right1 & 0x3f] | $spfunction1[DE_RM($right2, 24) & 0x3f] |
                            $spfunction3[DE_RM($right2, 16) & 0x3f] | $spfunction5[DE_RM($right2, 8) & 0x3f] |
                            $spfunction7[$right2 & 0x3f]));
                }
                $temp = $left;
                $left = $right;
                $right = $temp;
            }

            $left = (DE_RM($left, 1) | ($left << 31));
            $right = (DE_RM($right, 1) | ($right << 31));

            $temp = (DE_RM($left, 1) ^ $right) & 0x55555555;
            $right ^= $temp;
            $left ^= ($temp << 1);
            $temp = (DE_RM($right, 8) ^ $left) & 0x00ff00ff;
            $left ^= $temp;
            $right ^= ($temp << 8);
            $temp = (DE_RM($right, 2) ^ $left) & 0x33333333;
            $left ^= $temp;
            $right ^= ($temp << 2);
            $temp = (DE_RM($left, 16) ^ $right) & 0x0000ffff;
            $right ^= $temp;
            $left ^= ($temp << 16);
            $temp = (DE_RM($left, 4) ^ $right) & 0x0f0f0f0f;
            $right ^= $temp;
            $left ^= ($temp << 4);

            if ($mode) {
                if ($encrypt) {
                    $cbcleft = $left;
                    $cbcright = $right;
                } else {
                    $left ^= $cbcleft2;
                    $right ^= $cbcright2;
                }
            }
            if ($encrypt) {
                $tempresult .= chr(DE_RM($left, 24)) .
                    chr(DE_RM($left, 16) & 0xff) .
                    chr(DE_RM($left, 8) & 0xff) .
                    chr($left & 0xff) .
                    chr(DE_RM($right, 24)) .
                    chr(DE_RM($right, 16) & 0xff) .
                    chr(DE_RM($right, 8) & 0xff) .
                    chr($right & 0xff);
            } else {
                // 解密时，最后一个字符如果是\0，去除
                $tmpCh = (DE_RM($left, 16) & 0xffff);
                if (0 != $tmpCh) {
                    $tempresult .= chr($tmpCh);
                }
                $tmpCh = ($left & 0xffff);
                if (0 != $tmpCh) {
                    $tempresult .= chr($tmpCh);
                }
                $tmpCh = (DE_RM($right, 16) & 0xffff);
                if (0 != $tmpCh) {
                    $tempresult .= chr($tmpCh);
                }
                $tmpCh = ($right & 0xffff);
                if (0 != $tmpCh) {
                    $tempresult .= chr($tmpCh);
                }
            }
            $chunk += $encrypt ? 16 : 8;
            if (512 == $chunk) {
                $result .= $tempresult;
                $tempresult = '';
                $chunk = 0;
            }
        }

        return $result . $tempresult;
    }

    /**
     * 加密数据
     *
     * @Author YangHB
     * @DateTime 2021-10-04 17:41:08
     *
     * @param string $beinetStr
     * @param string $beinetkey
     * @return string
     */
    function encMe(string $beinetStr, string $beinetkey): string
    {
        if (null == $beinetkey || strlen($beinetkey) <= 0) {
            return '';
        }

        return DE_stringToHex(DE_des($beinetkey, $beinetStr, true, false, ''));
    }

    /**
     * 解密数据
     *
     * @Author YangHB
     * @DateTime 2021-10-04 17:41:08
     *
     * @param string $beinetStr
     * @param string $beinetkey
     * @return string
     */
    function uncMe(string $beinetStr, string $beinetkey): string
    {
        if (null == $beinetkey || strlen($beinetkey) <= 0) {
            return '';
        }
        return DE_des($beinetkey, DE_HexTostring($beinetStr), false, false, '');
    }
}

// 数组
if (!function_exists('array_merge_depth')) {
    /**
     * 深度合并
     * @param $arr1
     * @param $arr2
     * @return array
     */
    function array_merge_depth($arr1, $arr2): array
    {
        foreach ($arr2 as $key => $item) {
            if (!is_array($item)) {
                $arr1 = array_merge($arr1, [$key => $item]);
            } else {
                if (empty($arr1[$key]) || !is_array($arr1[$key])) {
                    $arr1 = array_merge($arr1, [$key => $item]);
                } else {
                    $arr1[$key] = array_merge_depth($arr1[$key], $item);
                }
            }
        }

        return $arr1;
    }
}
if (!function_exists('array_merge_depth_many')) {
    /**
     * 深度合并-多数组
     * @param $arr1
     * @param $arg
     * @return array
     */
    function array_merge_depth_many($arr1, ...$arg): array
    {
        if (!empty($arg[0]) && is_array($arg[0])) {
            foreach ($arg as $arr) {
                if (is_array($arr)) {
                    $arr1 = array_merge($arr1, array_merge_depth($arr1, $arr));
                }
            }
        } else {
            $arr1 = array_merge($arr1, $arg);
        }

        return $arr1;
    }
}

// 时间
if (!function_exists('format_time')) {
    /**
     * 格式化时间
     *
     * @param int $time
     * @param string $format
     * @return false|string
     */
    function format_time(int $time, string $format = 'Y-m-d H:i:s'): bool|string
    {
        if ($time > 0) {
            return date($format, $time);
        }

        return '';
    }
}

// 订单
if (!function_exists('order_no')) {
    /**
     * 订单编号
     *
     * @param  string  $prefix
     * @return string
     */
    function order_no(string $prefix): string
    {
        $num = \app\cache\OrderNoCache::getInstance()->incr($prefix, 1, 60);
        return $prefix . date('YmdHis') . sprintf("%04d", $num);
    }
}

// 距离
if (!function_exists('distance_m_to_km')) {
    /**
     * 距离
     *
     * @param  int  $distance
     * @param  int  $scale
     * @return array
     */
    function distance_m_to_km(int $distance, int $scale = 1000): array
    {
        $distanceKm = bcdiv($distance, $scale, 2);
        if ($distanceKm > 1) {
            return [$distanceKm, 'km'];
        }

        return [$distance, 'm'];
    }
}

// 分页没数据
if (!function_exists('empty_list')) {
    /**
     * 分页没数据
     * @return array
     */
    function empty_list(): array
    {
        return [
            'total'        => 0,
            'per_page'     => 1,
            'current_page' => 1,
            'last_page'    => 1,
            'data'         => [],
        ];
    }
}



if (!function_exists('to_tree_struct')) {
    /**
     * 转树结构
     *
     * @param  array  $list
     * @param  string  $indexKey 主键id
     * @param  string  $pid 父级id
     * @param  bool  $forceChildren 是否强制子级，有子级才显示
     * @param  Closure|null  $callback
     * @return array
     */
    function to_tree_struct(array $list, string $indexKey = "sysId", string $pid = "pid", bool $forceChildren = false, ?Closure $callback = null): array
    {
        $list = array_column($list, null, $indexKey);
        $tree = [];
        foreach ($list as &$item) {
            $itemCopy = $item;
            //匿名函数调用(外部自定义)
            if (!empty($callback)) {
                $item = $callback($item);
            }

            //固定的处理代码
            if (isset($list[$itemCopy[$pid]])) {
                $list[$itemCopy[$pid]]['children'][] = &$list[$itemCopy[$indexKey]];
            } else {
                // 记录一级。其它等级会赋值给 children
                if ($itemCopy[$pid] == 0) {
                    $tree[] = &$list[$itemCopy[$indexKey]];
                }
            }
        }

        if ($forceChildren) {
            $newTree = [];
            foreach ($tree as $item1) {
                if (!empty($item1['children'])) {
                    $newTree[] = $item1;
                }
            }
            $tree = $newTree;
        }

        //树结构
        return $tree;
    }
}

if (!function_exists('event')) {
    /**
     * 触发事件
     * @param mixed $event 事件名（或者类名）
     * @param mixed $args 参数
     * @param int $delay
     * @param int $retryMax
     * @return mixed
     */
    function event($event, $args = null, int $delay = -1, int $retryMax = 0)
    {
        return Event::setDelay($delay)->setRetryMax($retryMax)->trigger($event, $args);
    }
}

if (!function_exists('get_env')) {
    /**
     * 获取环境变量
     *
     * @Author YangHB
     * @DateTime 2022-10-04 09:00:19
     *
     * @param string $key
     * @param mixed $defaultValue
     * @return mixed
     */
    function get_env(string $key, $defaultValue = '')
    {
        if (empty($key)) {
            return $defaultValue;
        }
        $result = getenv(str_replace('.', '_', $key));
        if ($result !== false && $result !== '') {
            return $result;
        }
        return env($key, $defaultValue);
    }
}

if (!function_exists('get_month_start_end')) {
    /**
     * 获取指定年月的开始结束时间
     *
     * @param  string  $date
     * @return array
     */
    function get_month_start_end(string $date = ''): array
    {
        if (empty($date)) {
            $date = date('Y-m');
        }

        $beginThisMonth = strtotime($date);
        $endDay = date( 't', $beginThisMonth);
        $endThisMonth = strtotime(date('Y-m-' . $endDay . ' 23:59:59', $beginThisMonth));

        return [$beginThisMonth, $endThisMonth];
    }
}


//记录日志函数
if (!function_exists('LogWrite')) {
    /**
     * 底层输出日志
     *
     * @Author YangHB
     * @DateTime 2022-07-13 13:34:24
     *
     * @param string $level
     * @param string $chan
     * @param string $title
     * @param string $msg
     * @param array $content
     * @param array $param
     * @return void
     */
    function LogWrite(string $level, string $chan, string $title, string $msg, array $content = [], array $param = [])
    {
        Log::$level([
            'chan' => $chan,
            'title' => $title,
            'msg' => $msg,
            'content' => $content,
            'file_line' => Trace::getInstance()->getFileLine(),
        ], $param);
    }
}
if (!function_exists('LogInfo')) {
    /**
     * 记录 Info 组别日志
     *
     * @Author YangHB
     * @DateTime 2022-07-13 11:28:59
     *
     * @param string $chan
     * @param string $title
     * @param string $msg
     * @param array $content
     * @param array $param
     * @return void
     */
    function LogInfo(string $chan, string $title, string $msg, array $content = [], array $param = [])
    {
        LogWrite('info', $chan, $title, $msg, $content, $param);
    }
}
if (!function_exists('LogWarning')) {
    /**
     * 记录警告组别日志
     *
     * @Author YangHB
     * @DateTime 2022-07-13 11:30:12
     *
     * @param string $chan
     * @param string $title
     * @param string $msg
     * @param array $content
     * @param array $param
     * @return void
     */
    function LogWarning(string $chan, string $title, string $msg, array $content = [], array $param = [])
    {
        LogWrite('warning', $chan, $title, $msg, $content, $param);
    }
}
if (!function_exists('LogError')) {
    /**
     * 记录错误级别日志信息
     *
     * @Author YangHB
     * @DateTime 2022-07-13 11:30:56
     *
     * @param string $chan
     * @param string $title
     * @param string $msg
     * @param array $content
     * @param array $param
     * @return void
     */
    function LogError(string $chan, string $title, string $msg, array $content = [], array $param = [])
    {
        LogWrite('error', $chan, $title, $msg, $content, $param);
    }
}
if (!function_exists('LogAlert')) {
    /**
     * 记录警醒级别日志信息
     *
     * @Author YangHB
     * @DateTime 2022-07-13 11:31:30
     *
     * @param string $chan
     * @param string $title
     * @param string $msg
     * @param array $content
     * @param array $param
     * @return void
     */
    function LogAlert(string $chan, string $title, string $msg, array $content = [], array $param = [])
    {
        LogWrite('alert', $chan, $title, $msg, $content, $param);
    }
}
if (!function_exists('LogCritical')) {
    /**
     * 记录紧急型错误信息
     *
     * @Author YangHB
     * @DateTime 2022-07-13 11:33:13
     *
     * @param string $chan
     * @param string $title
     * @param string $msg
     * @param array $content
     * @param array $param
     * @return void
     */
    function LogCritical(string $chan, string $title, string $msg, array $content = [], array $param = [])
    {
        LogWrite('critical', $chan, $title, $msg, $content, $param);
    }
}
if (!function_exists('LogDebug')) {
    /**
     * 记录调整日志错误信息
     *
     * @Author YangHB
     * @DateTime 2022-07-13 11:33:48
     *
     * @param string $chan
     * @param string $title
     * @param string $msg
     * @param array $content
     * @param array $param
     * @return void
     */
    function LogDebug(string $chan, string $title, string $msg, array $content = [], array $param = [])
    {
        LogWrite('debug', $chan, $title, $msg, $content, $param);
    }
}